//
//  SQLite3Connector.m
//  SQLite3Connector
//
//  Created by Ondrej Rafaj on 26.10.09.
//  Copyright 2009 Home. All rights reserved.
//

#import "SQLite3Connector.h"


@implementation SQLite3Connector


+ (NSString *) escapeString:(NSString *)string {
	return string;
}

+ (NSString *) getDocumentsDirectoryPath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	return [paths objectAtIndex:0];
}

+ (NSString *) getDatabaseFolderPath {
	BOOL isDir;
	NSString *path = [NSString stringWithFormat:@"%@/%@/", [self getDocumentsDirectoryPath], @"sqlite3connector"];
	NSFileManager *fileManager = [NSFileManager defaultManager];
	if ([fileManager fileExistsAtPath:path isDirectory:&isDir] && isDir) return path;
	else {
		if ([fileManager createDirectoryAtPath:path attributes:nil]) return path;
		else NSAssert1(0, @"Can't create '%@' folder in your documents directory",  @"sqlite3connector");
	}
	return path;
}

+ (NSString *) getDatabasePathFromName:(NSString *)databaseName {
	return [NSString stringWithFormat:@"%@%@.sqlite3", [self getDatabaseFolderPath], databaseName];
}

+ (BOOL) databaseExists:(NSString *)databaseName {
	BOOL isDir;
	NSFileManager *fileManager = [NSFileManager defaultManager];
	if ([fileManager fileExistsAtPath:[self getDatabasePathFromName:databaseName] isDirectory:&isDir]) {
		if (isDir) return NO;
		else return YES;
	}
	else return NO;
}

+ (void) checkDatabase:(NSString *)databaseName {
	if (![self databaseExists:databaseName]) NSAssert1(0, @"Database '%@' does not exists", databaseName);
}

+ (NSArray *) getTablesInDatabase:(NSString *)databaseName {
	[self checkDatabase:databaseName];
	NSArray *arr = [[NSArray alloc] init];
	
	return arr;
}

+ (BOOL) dropDatabase:(NSString *)databaseName {
	[self checkDatabase:databaseName];
	NSFileManager *fileManager = [NSFileManager defaultManager];
	return [fileManager removeItemAtPath:[self getDatabasePathFromName:databaseName] error:nil];
	
}

+ (NSArray *) getDatabaseFilePaths:(NSString *)path {
	NSArray *arr = [[NSArray alloc] init];
	
	return arr;
}

+ (int) getDatabaseFileSize:(NSString *)databaseName {
	NSFileManager *manager = [NSFileManager defaultManager];
	NSDictionary *fileAttributes = [manager fileAttributesAtPath:[self getDatabasePathFromName:databaseName] traverseLink:false];
	int ret = [[fileAttributes objectForKey:NSFileSize] intValue];
	return ret;
}

+ (NSString *) getDatabaseFormatedFileSize:(NSString *)databaseName {
	int fileSize = [self getDatabaseFileSize:databaseName];
	NSString *extension = [NSString alloc];
	NSString *formatedFileSize = [NSString alloc];
	float ff;
	if (fileSize < 1024) {
		formatedFileSize = [NSString stringWithFormat:@"%d", fileSize];
		extension = @"bytes";
	}
	else if (fileSize < 1048576) {
		ff = (float) fileSize / 1024.00;
		formatedFileSize = [NSString stringWithFormat:@"%.2f", ff];
		extension = @"Kb";
	}
	else {
		ff = (float) fileSize / 1048576;
		formatedFileSize = [NSString stringWithFormat:@"%.2f", ff];
		extension = @"Mb";
	}
	return [NSString stringWithFormat:@"%@ %@", formatedFileSize, extension];
}


- (BOOL) _connect:(NSString *)databaseName {
	BOOL ok;
	if (sqlite3_open([[SQLite3Connector getDatabasePathFromName:databaseName] UTF8String], &database) != SQLITE_OK) {
		sqlite3_close(database);
		NSAssert1(0, @"Failed to open the database: %@", databaseName);
		ok = NO;
	}
	else ok = YES;
	return ok;
}

- (BOOL) executeQuery:(NSString *)query inDatabase:(NSString *)databaseName {
	BOOL ok = NO;
	if ([self _connect:databaseName]) {
		char *errorMsg;
		if (sqlite3_exec(database, [query UTF8String], NULL, NULL, &errorMsg) != SQLITE_OK) {
			sqlite3_close(database);
			NSAssert2(0, @"SQLite Error: %s (%@)", errorMsg, databaseName);
		}
		else ok = YES;
		sqlite3_close(database);
	}
	return ok;
}

- (int) executeScalar:(NSString *)query inDatabase:(NSString *)databaseName {
	int value = 0;
	if ([self _connect:databaseName]) {
		sqlite3_stmt *statement;
		if (sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil) == SQLITE_OK) {
			while (sqlite3_step(statement) == SQLITE_ROW) {
				value = sqlite3_column_int(statement, 0);
				break;
			}
		}
		sqlite3_close(database);
	}
	return value;
}

- (BOOL) tableExists:(NSString *)tableName inDatabase:(NSString *)databaseName {
	NSString *query = [NSString stringWithFormat:@"SELECT COUNT(name) FROM sqlite_master WHERE name = '%@';", tableName];
	int is = [self executeScalar:query inDatabase:databaseName];	
	return is;
}

- (BOOL) truncateTable:(NSString *)tableName inDatabase:(NSString *)databaseName {
	NSString *query = [NSString stringWithFormat:@"DELETE FROM  %@;", tableName];
	return [self executeQuery:query inDatabase:databaseName];
}

- (BOOL) truncateTable:(NSString *)tableName inDatabase:(NSString *)databaseName useVacuum:(BOOL)use {
	BOOL ok = [self truncateTable:tableName inDatabase:databaseName];
	[self executeQuery:@"VACUUM;" inDatabase:databaseName];
	return ok;
}

- (BOOL) dropTable:(NSString *)tableName inDatabase:(NSString *)databaseName {
	NSString *query = [NSString stringWithFormat:@"DROP TABLE IF EXISTS %@;", tableName];
	return [self executeQuery:query inDatabase:databaseName];
}

- (BOOL) dropTable:(NSString *)tableName inDatabase:(NSString *)databaseName useVacuum:(BOOL)use {
	BOOL ok = [self dropTable:tableName inDatabase:databaseName];
	[self executeQuery:@"VACUUM;" inDatabase:databaseName];
	return ok;
}

- (NSMutableArray *) getTablesInDatabase:(NSString *)databaseName {
	NSString *query = @"SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name;";
	//NSMutableArray *data = [self getData:query fromDatabase:databaseName];
	NSMutableArray *arr = [[NSMutableArray alloc] init];
	if ([self _connect:databaseName]) {
		sqlite3_stmt *statement;
		if (sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil) == SQLITE_OK) {
			while (sqlite3_step(statement) == SQLITE_ROW) {
				char *cName = (char *) sqlite3_column_text(statement, 0);
				NSString *name = [NSString stringWithFormat:@"%s", cName];
				[arr addObject:name];
			}
		}
	}
	return arr;
}

- (NSMutableArray *) getData:(NSString *)query fromDatabase:(NSString *)databaseName {
	NSMutableArray *arr = [[NSMutableArray alloc] init];
	if ([self _connect:databaseName]) {
		sqlite3_stmt *statement;
		if (sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil) == SQLITE_OK) {
			while (sqlite3_step(statement) == SQLITE_ROW) {
				NSMutableDictionary *row = [[NSMutableDictionary alloc] init];
				int columns = sqlite3_column_count(statement);
				for (int i = 0; i < columns; i++) {
					long type = sqlite3_column_type(statement, i);
					char *name = (char *) sqlite3_column_name(statement, i);
					NSString *value = [[NSString alloc] init];
					switch(type) {
						case SQLITE_INTEGER:
							value = [NSString stringWithFormat:@"%d", sqlite3_column_int(statement, i)];
							break;
							
						case SQLITE_FLOAT:
							value = [NSString stringWithFormat:@"%f", sqlite3_column_double(statement, i)];
							break;
							
						case SQLITE_TEXT:
							value = [NSString stringWithFormat:@"%s", sqlite3_column_text(statement, i)];
							break;
							
						case SQLITE_BLOB:
							value = [NSString stringWithFormat:@"%d", sqlite3_column_bytes(statement, i)];
							break;
							
						case SQLITE_NULL:
							break;
							
						default:
							break;
					}
					[row setValue:value forKey:[NSString stringWithFormat:@"%s", name]];
				}
				[arr addObject:[row copy]];
			}
		}
		sqlite3_close(database);
	}
	return arr;
}


@end
